using Microsoft.AspNetCore.Mvc;
using AuthService.Application.Services;
using Microsoft.AspNetCore.Authorization;

namespace AuthService.Api.Controllers;

/// <summary>
/// 认证控制器
/// 提供用户登录、注册、令牌刷新等认证相关功能
/// </summary>
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class AuthController : ControllerBase
{
    private readonly IUserServiceSimplified _userService;
    private readonly ILogger<AuthController> _logger;

    public AuthController(IUserServiceSimplified userService, ILogger<AuthController> logger)
    {
        _userService = userService;
        _logger = logger;
    }

    /// <summary>
    /// 用户登录
    /// </summary>
    /// <param name="request">登录请求</param>
    /// <returns>登录结果</returns>
    /// <response code="200">登录成功</response>
    /// <response code="400">请求参数错误</response>
    /// <response code="401">用户名或密码错误</response>
    /// <response code="423">账户已被锁定</response>
    /// <response code="500">服务器内部错误</response>
    [HttpPost("login")]
    [AllowAnonymous]
    [ProducesResponseType(typeof(LoginResponse), 200)]
    [ProducesResponseType(typeof(ErrorResponse), 400)]
    [ProducesResponseType(typeof(ErrorResponse), 401)]
    [ProducesResponseType(typeof(ErrorResponse), 423)]
    [ProducesResponseType(typeof(ErrorResponse), 500)]
    public async Task<IActionResult> Login([FromBody] LoginRequestDto request)
    {
        try
        {
            _logger.LogInformation("收到登录请求: {UsernameOrEmail}", request.UsernameOrEmail);

            // 验证请求参数
            if (string.IsNullOrWhiteSpace(request.UsernameOrEmail))
            {
                return BadRequest(new ErrorResponse
                {
                    ErrorCode = "INVALID_INPUT",
                    ErrorMessage = "用户名或邮箱不能为空"
                });
            }

            if (string.IsNullOrWhiteSpace(request.Password))
            {
                return BadRequest(new ErrorResponse
                {
                    ErrorCode = "INVALID_INPUT",
                    ErrorMessage = "密码不能为空"
                });
            }

            // 构建登录请求
            var loginRequest = new LoginRequest
            {
                UsernameOrEmail = request.UsernameOrEmail.Trim(),
                Password = request.Password,
                RememberMe = request.RememberMe,
                ClientIp = GetClientIpAddress(),
                UserAgent = Request.Headers.UserAgent.ToString(),
                TenantId = request.TenantId
            };

            // 执行登录验证（简化版本）
            var (isValid, user) = await _userService.ValidateUserLoginAsync(loginRequest.UsernameOrEmail, loginRequest.Password);

            if (!isValid || user == null)
            {
                return Unauthorized(new ErrorResponse
                {
                    ErrorCode = "INVALID_CREDENTIALS",
                    ErrorMessage = "用户名或密码错误"
                });
            }

            // 登录成功，构建响应（简化版本）
            var response = new LoginResponse
            {
                Success = true,
                Message = "登录成功",
                User = new UserInfo
                {
                    Id = user.Id,
                    Username = user.Username,
                    Email = user.Email,
                    DisplayName = user.DisplayName
                },
                Permissions = null, // 简化版本暂无权限系统
                LoginTime = DateTime.UtcNow,
                SessionId = Guid.NewGuid().ToString(),
                // 简化版本使用演示令牌
                AccessToken = "demo-token-" + Guid.NewGuid().ToString("N")[..16],
                RefreshToken = null,
                ExpiresAt = DateTime.UtcNow.AddHours(24)
            };

            _logger.LogInformation("用户登录成功: {Username}", user.Username);
            return Ok(response);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "登录处理过程中发生异常");
            return StatusCode(500, new ErrorResponse
            {
                ErrorCode = "INTERNAL_ERROR",
                ErrorMessage = "服务器内部错误，请稍后重试"
            });
        }
    }

    /// <summary>
    /// 用户注册（预留）
    /// </summary>
    /// <param name="request">注册请求</param>
    /// <returns>注册结果</returns>
    [HttpPost("register")]
    [AllowAnonymous]
    [ProducesResponseType(typeof(RegisterResponse), 200)]
    [ProducesResponseType(typeof(ErrorResponse), 400)]
    [ProducesResponseType(typeof(ErrorResponse), 409)]
    [ProducesResponseType(typeof(ErrorResponse), 500)]
    public async Task<IActionResult> Register([FromBody] RegisterRequestDto request)
    {
        // 预留给注册功能实现
        return Ok(new RegisterResponse
        {
            Success = true,
            Message = "注册功能将在后续版本中实现"
        });
    }

    /// <summary>
    /// 刷新令牌（预留）
    /// </summary>
    /// <param name="request">刷新令牌请求</param>
    /// <returns>新的令牌</returns>
    [HttpPost("refresh")]
    [ProducesResponseType(typeof(RefreshTokenResponse), 200)]
    [ProducesResponseType(typeof(ErrorResponse), 401)]
    [ProducesResponseType(typeof(ErrorResponse), 500)]
    public async Task<IActionResult> RefreshToken([FromBody] RefreshTokenRequestDto request)
    {
        // 预留给双token实现
        return Ok(new RefreshTokenResponse
        {
            Success = true,
            Message = "令牌刷新功能将在后续版本中实现"
        });
    }

    /// <summary>
    /// 用户登出（预留）
    /// </summary>
    /// <returns>登出结果</returns>
    [HttpPost("logout")]
    [Authorize]
    [ProducesResponseType(typeof(LogoutResponse), 200)]
    [ProducesResponseType(typeof(ErrorResponse), 401)]
    [ProducesResponseType(typeof(ErrorResponse), 500)]
    public async Task<IActionResult> Logout()
    {
        // 预留给登出功能实现
        return Ok(new LogoutResponse
        {
            Success = true,
            Message = "登出成功"
        });
    }

    /// <summary>
    /// 获取客户端IP地址
    /// </summary>
    private string? GetClientIpAddress()
    {
        // 尝试从X-Forwarded-For头获取真实IP
        var forwardedFor = Request.Headers["X-Forwarded-For"].FirstOrDefault();
        if (!string.IsNullOrEmpty(forwardedFor))
        {
            return forwardedFor.Split(',')[0].Trim();
        }

        // 尝试从X-Real-IP头获取
        var realIp = Request.Headers["X-Real-IP"].FirstOrDefault();
        if (!string.IsNullOrEmpty(realIp))
        {
            return realIp;
        }

        // 使用连接的远程IP
        return HttpContext.Connection.RemoteIpAddress?.ToString();
    }

    /// <summary>
    /// 简单登录验证测试（演示密码哈希验证过程）
    ///
    /// 这个端点专门用于演示密码哈希值和盐值的验证过程：
    ///
    /// 验证流程：
    /// 1. 接收用户名和明文密码
    /// 2. 根据用户名查找用户记录（包含存储的哈希值和盐值）
    /// 3. 使用PBKDF2算法重新计算哈希值：
    ///    - 用户输入的密码 + 数据库中的盐值 → PBKDF2(10000次迭代) → 新哈希值
    /// 4. 比较新计算的哈希值与数据库存储的哈希值
    /// 5. 相同则验证成功，不同则验证失败
    ///
    /// 安全特性演示：
    /// - PBKDF2算法：通过10000次迭代增加破解成本
    /// - 唯一盐值：每个用户都有不同的32字节随机盐值
    /// - 单向加密：无法从哈希值反推出原始密码
    /// - 防彩虹表：相同密码在不同用户中产生不同哈希值
    ///
    /// 测试用例：
    /// - 用户名: testuser
    /// - 密码: password123
    /// </summary>
    /// <param name="request">简单登录请求</param>
    /// <returns>验证结果和详细说明</returns>
    [HttpPost("test-login")]
    [AllowAnonymous]
    [ProducesResponseType(typeof(object), 200)]
    [ProducesResponseType(typeof(object), 400)]
    [ProducesResponseType(typeof(object), 401)]
    [ProducesResponseType(typeof(object), 500)]
    public async Task<IActionResult> TestLoginAsync([FromBody] SimpleLoginRequest request)
    {
        try
        {
            _logger.LogInformation("密码验证测试请求: {Username}", request.Username);

            // 步骤1：验证请求参数
            if (string.IsNullOrWhiteSpace(request.Username) || string.IsNullOrWhiteSpace(request.Password))
            {
                return BadRequest(new
                {
                    success = false,
                    error = "参数错误",
                    message = "用户名和密码不能为空",
                    explanation = "请提供有效的用户名和密码进行测试"
                });
            }

            // 步骤2：调用密码验证服务
            // 这里会执行完整的密码哈希验证流程
            var (isValid, user) = await _userService.ValidateUserLoginAsync(request.Username, request.Password);

            if (!isValid || user == null)
            {
                return Unauthorized(new
                {
                    success = false,
                    error = "验证失败",
                    message = "用户名或密码错误",
                    explanation = new
                    {
                        process = "密码验证过程",
                        steps = new[]
                        {
                            "1. 根据用户名查找用户记录",
                            "2. 检查用户是否存在且未被删除",
                            "3. 获取数据库中存储的密码哈希值和盐值",
                            "4. 使用输入密码+存储盐值通过PBKDF2算法计算新哈希值",
                            "5. 比较新哈希值与存储哈希值",
                            "6. 验证失败：哈希值不匹配"
                        },
                        security_features = new
                        {
                            algorithm = "PBKDF2 with SHA256",
                            iterations = 10000,
                            salt_length = "32 bytes (256 bits)",
                            hash_length = "32 bytes (256 bits)"
                        }
                    }
                });
            }

            // 步骤3：验证成功，返回详细信息
            return Ok(new
            {
                success = true,
                message = "密码验证成功！",
                user = new
                {
                    id = user.Id,
                    username = user.Username,
                    email = user.Email,
                    displayName = user.DisplayName,
                    createdAt = user.CreatedAt
                },
                verification_process = new
                {
                    description = "密码哈希验证成功完成",
                    steps_completed = new[]
                    {
                        "✓ 1. 根据用户名找到用户记录",
                        "✓ 2. 确认用户存在且状态正常",
                        "✓ 3. 获取存储的密码哈希值和盐值",
                        "✓ 4. 使用PBKDF2算法重新计算哈希值",
                        "✓ 5. 哈希值匹配，验证成功"
                    },
                    security_explanation = new
                    {
                        password_storage = "密码以PBKDF2哈希值形式安全存储，永不保存明文",
                        salt_purpose = "每用户唯一的32字节盐值防止彩虹表攻击",
                        pbkdf2_benefit = "10000次迭代大大增加暴力破解成本",
                        one_way_encryption = "哈希算法单向，无法从哈希值恢复原始密码"
                    }
                },
                demo_token = "demo-" + Guid.NewGuid().ToString("N")[..16],
                timestamp = DateTime.UtcNow
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "密码验证测试异常: {Username}", request.Username);
            return StatusCode(500, new
            {
                success = false,
                error = "服务器错误",
                message = "验证过程中发生异常",
                details = ex.Message
            });
        }
    }
}

/// <summary>
/// 简单登录请求模型
/// </summary>
public class SimpleLoginRequest
{
    /// <summary>
    /// 用户名
    /// </summary>
    public string Username { get; set; } = string.Empty;

    /// <summary>
    /// 密码
    /// </summary>
    public string Password { get; set; } = string.Empty;
}

#region DTO Models

/// <summary>
/// 登录请求DTO
/// </summary>
public class LoginRequestDto
{
    /// <summary>
    /// 用户名或邮箱
    /// </summary>
    public string UsernameOrEmail { get; set; } = string.Empty;

    /// <summary>
    /// 密码
    /// </summary>
    public string Password { get; set; } = string.Empty;

    /// <summary>
    /// 是否记住登录状态
    /// </summary>
    public bool RememberMe { get; set; } = false;

    /// <summary>
    /// 租户ID
    /// </summary>
    public string? TenantId { get; set; }
}

/// <summary>
/// 登录响应
/// </summary>
public class LoginResponse
{
    /// <summary>
    /// 是否成功
    /// </summary>
    public bool Success { get; set; }

    /// <summary>
    /// 消息
    /// </summary>
    public string Message { get; set; } = string.Empty;

    /// <summary>
    /// 用户信息
    /// </summary>
    public UserInfo? User { get; set; }

    /// <summary>
    /// 权限信息
    /// </summary>
    public UserPermissionInfo? Permissions { get; set; }

    /// <summary>
    /// 访问令牌（预留）
    /// </summary>
    public string? AccessToken { get; set; }

    /// <summary>
    /// 刷新令牌（预留）
    /// </summary>
    public string? RefreshToken { get; set; }

    /// <summary>
    /// 令牌过期时间
    /// </summary>
    public DateTime? ExpiresAt { get; set; }

    /// <summary>
    /// 登录时间
    /// </summary>
    public DateTime LoginTime { get; set; }

    /// <summary>
    /// 会话ID
    /// </summary>
    public string? SessionId { get; set; }
}

/// <summary>
/// 用户信息
/// </summary>
public class UserInfo
{
    public Guid Id { get; set; }
    public string Username { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string? DisplayName { get; set; }
    public bool IsEmailVerified { get; set; }
    public DateTime? LastLoginAt { get; set; }
    public string? TenantId { get; set; }
}

/// <summary>
/// 错误响应
/// </summary>
public class ErrorResponse
{
    public string ErrorCode { get; set; } = string.Empty;
    public string ErrorMessage { get; set; } = string.Empty;
}

/// <summary>
/// 注册请求DTO（预留）
/// </summary>
public class RegisterRequestDto
{
    public string Username { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string Password { get; set; } = string.Empty;
    public string? DisplayName { get; set; }
}

/// <summary>
/// 注册响应（预留）
/// </summary>
public class RegisterResponse
{
    public bool Success { get; set; }
    public string Message { get; set; } = string.Empty;
}

/// <summary>
/// 刷新令牌请求DTO（预留）
/// </summary>
public class RefreshTokenRequestDto
{
    public string RefreshToken { get; set; } = string.Empty;
}

/// <summary>
/// 刷新令牌响应（预留）
/// </summary>
public class RefreshTokenResponse
{
    public bool Success { get; set; }
    public string Message { get; set; } = string.Empty;
    public string? AccessToken { get; set; }
    public string? RefreshToken { get; set; }
    public DateTime? ExpiresAt { get; set; }
}

/// <summary>
/// 登出响应（预留）
/// </summary>
public class LogoutResponse
{
    public bool Success { get; set; }
    public string Message { get; set; } = string.Empty;
}

#endregion
